package org.balthie.cal.impl.cmd.spec;

import java.util.Deque;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.balthie.cal.common.ex.InputException;
import org.balthie.cal.core.ICommand;

public class CmdsLiterallyRegexSpecs {

	public static final CmdsLiterallyRegexSpec IS_ZERO = new CmdsLiterallyRegexSpec("^0$");

	public static class CmdsLiterallyRegexSpec extends AbsCmdsSpec {

		private String expect;

		private String errorTips;

		private ICommand currentCmd;

		public CmdsLiterallyRegexSpec(String pattern) {
			this(pattern, null);
		}

		public CmdsLiterallyRegexSpec(String pattern, String errorTips) {
			this.expect = pattern;
			this.errorTips = errorTips;
		}

		public CmdsLiterallyRegexSpec(String pattern, String errorTips, ICommand currentCmd) {
			this.expect = pattern;
			this.errorTips = errorTips;
			this.currentCmd = currentCmd;
		}
		
		@Override
		public String getTips() {
			return this.errorTips;
		}

		@Override
		protected boolean doCheck(Deque<ICommand> candidate, boolean isThrow) {
			String cmdsLiterallyContent = "";
			if (!candidate.isEmpty()) {
				StringBuilder s = new StringBuilder();
				candidate.forEach(c -> s.append(c.getLiterally()));
				if(this.currentCmd != null) {
					s.append(this.currentCmd.getLiterally());
				}
				cmdsLiterallyContent = s.toString();
			}

			Pattern p = Pattern.compile(this.expect);
			Matcher m = p.matcher(cmdsLiterallyContent);

			Boolean isSatisfied = m.matches();
			if (!isSatisfied && isThrow) {
				String msg = errorTips != null ? errorTips
						: String.format("ERROR: %s [expectPattern = %s] [actually= %s]",
								this.getClass().getSimpleName(), this.expect, cmdsLiterallyContent);
				throw new InputException(msg);
			} else {
				return isSatisfied;
			}
		}
	}
}
